/*
CpGears v1.0

Copyright (c) 2010 Yves Riel http://www.flash-factor.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

package cpgears.views.manager {
	import cpgears.log.ILogger;
	import cpgears.log.LogManager;
	import cpgears.movie.IMovie;
	import cpgears.properties.IWidgetProperties;
	import cpgears.views.IRuntimeView;
	import cpgears.views.IWidgetView;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	
	/**
	 * A manager that will show the widget views.
	 * 
	 * <P>This manager will show only one view at a time. It will
	 * remove the previous view and display the view associated to
	 * the current widget state i.e. runtime, edit, stage or preview.</P>
	 * 
	 * @author Whyves
	 */
	public class StaticViewManager implements IWidgetViewManager{

		private var mRoot:DisplayObjectContainer = null;
		private const mViews:Array = new Array();
		private var mEditView:IWidgetView = null;
		private var mRuntimeView:IRuntimeView = null;
		private var mStageView:IWidgetView = null;
		private var mPreviewView:IWidgetView = null;
		private static var mLogger:ILogger = null;
		
		/**
		 * Creates the Simple View Manager.
		 * 
		 * <P>You can pass <code>null</code> for any parameter if the widget
		 * doesn't have anything to display for that particular mode. You can also pass
		 * the same view for many parameters if the view is the same for the different
		 * widget modes.</P>
		 * 
		 * @param	editView The view displayed when the widget is in the edit mode.
		 * @param	runtimeView The view displayed when the widget is in the runtime mode.
		 * @param	stageView The view displayed when the widget is in the Stage mode.
		 * @param	previewView The view displayed when the widget is in the preview mode.
		 */
		public function StaticViewManager(	editView:IWidgetView, runtimeView:IRuntimeView,
											stageView:IWidgetView, previewView:IWidgetView) {
										
			mLogger = LogManager.getLogger(this);							
			
			mEditView = editView;
			mViews.push(mEditView);
			mRuntimeView = runtimeView;
			mViews.push(mRuntimeView);
			mStageView = stageView;
			mViews.push(mStageView);
			mPreviewView = previewView;
			mViews.push(mPreviewView);
		}
		
		/**
		 * @inheritDoc
		 */
		public function get rootContainer():DisplayObjectContainer {
			if (mRoot == null) mLogger.warn("The root container was not set before displaying the Wiget Views.");
			return (mRoot != null) ? mRoot : new Sprite();
		}

		public function set rootContainer(value:DisplayObjectContainer):void {
			if (value == null) swapView(null);
			mRoot = value;
		}
		
		/**
		 * Initializes the Flash Player stage.
		 * 
		 * @param	scaleMode The stage scale mode.
		 * @param	align The alignment with respect to the stage.
		 */
		protected function initializeStage(scaleMode:String, align:String):void {
			if (!mRoot.stage) return;
			
			try {
				mRoot.stage.scaleMode = scaleMode;
			} catch (err:Error) {
				mLogger.error("Could not set the Stage scale mode to '{0}'. Ensure that the widget view sets a proper value.", scaleMode);
			}

			try {
				mRoot.stage.align = align;
			} catch (err:Error) {
				mLogger.error("Could not set the Stage align to '{0}'. Ensure that the widget view sets a proper value.", align);
			}
		}
		
		/**
		 * @inheritDoc
		 */
		public function showEditView(widgetProperties:IWidgetProperties):void {
			if (mEditView != null) configureView(mEditView, widgetProperties);
		}
		
		/**
		 * @inheritDoc
		 */
		public function showPreview(widgetProperties:IWidgetProperties):void{
			if (mPreviewView != null) configureView(mPreviewView, widgetProperties);
		}
		
		/**
		 * @inheritDoc
		 */
		public function showRuntimeView(widgetProperties:IWidgetProperties, movie:IMovie):void {
			if (mRuntimeView != null) {
				mRuntimeView.movie = movie;
				configureView(mRuntimeView, widgetProperties);
				
				// KLUDGE: Captivate forces the stage when in preview mode. Need to ensure that it stays that way.
				if (movie.isPreview()) {
					mRoot.stage.align = StageAlign.TOP_LEFT;
					mRoot.stage.scaleMode = StageScaleMode.NO_SCALE;
				}
			}
		}
		
		/**
		 * @inheritDoc
		 */
		public function showStageView(widgetProperties:IWidgetProperties):void {
			if (mStageView != null) configureView(mStageView, widgetProperties);
		}
		
		/**
		 * @private
		 */
		private function configureView(view:IWidgetView, widgetProperties:IWidgetProperties):void {
				view.widgetProperties = widgetProperties;
				swapView(view);
				view.initialize();
		}
		
		/**
		 * @private
		 */
		private function swapView(viewToDisplay:IWidgetView):void {
			for each (var view:IWidgetView in mViews) {
				if (view == null) continue;		// View is null so we cannot do anything.
				try {
					if (view == viewToDisplay) {
						initializeStage(view.stageScaleMode, view.stageAlign);
						rootContainer.addChild(DisplayObject(view));
					} else if (rootContainer.contains(DisplayObject(view))) {
						rootContainer.removeChild(DisplayObject(view));
					}
				} catch (err:Error) {
						mLogger.error("The widget view '{0}' could not be added/removed from the widget container '{1}'.", view, rootContainer.name);
				}
			}
		}
	}

}